package com.atguigu.gulimall.order.config;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class MyRabbitConfig {

    //TODO 循环依赖问题需要解决
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }


    //发送端确认
    //1、只要消息成功抵达服务器，就会触发，不管是否消费了
    //pulisher -> broker 消息抵达代理，即rabbitMQ 就好触发打印ack为true
    //定制rabbitTemplate
    //设置确认回掉
    //消息收到后，后执行这个方法
    @PostConstruct  //对象创建完成之后执行这个方法
    public void initRabbitTemplate(){

        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback(){

            //correlationData 当前消息的唯一id
            //ack 消息时候成功收到
            //cause 失败的原因
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                /**
                 * 1、做好消息确认机制 消费成功才ACk
                 * 2、每一个消息在数据库做好记录，定期扫描失败的消息再次发送
                 * 3、发送成功之后设置状态为成功
                 */
                //到这服务器就将消息持久化到队列里面了，永远不会丢失了
                System.out.println("ack:"+ack);
            }
        });

        //触发时机，只要消息没有投递给指定的队列，触发回掉
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback(){
            //到这说明消息没有投递成功
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routerKey) {
                System.out.println("fail message:"+message+"reply Code:"+replyCode+"reply text:" + replyText+"exchange:"+exchange+"router key:"+ routerKey);
            }
        });

    }

    //消费端确认 - 监视消费者是否成功消费消息
    //为了保证每个消息都被成功消费，通道一打开，消息就会自动确认接收，
    // 如果这时服务器宕机了，就会导致没有已经被接受却没有没处理的消息也自动确认
    //因为是一下子接受到很多消息，全部自动回回复了，而被处理成功的只是某个消息，其他消息没有处理成功，也被视为已接收然后删除
    //可以开启手动确认


}
